;(function(root, $, undefined) {

/**
 * The jQuery plugin namespace.
 * @external "jQuery.fn"
 * @see {@link http://learn.jquery.com/plugins/|jQuery Plugins}
 */

/**
 * @namespace UCDX
 */
var UCDX = root.UCDX || (root.UCDX = { });

Array.isArray = Array.isArray || function(a) {
	return a && a.length !== undefined;
};
Array.prototype.map = Array.prototype.map || function(fn) {
	for (var i = 0, len = this.length, ret = []; i < len; i++) {
		ret.push(fn(this[i]));
	}
	return ret;
};

var dproto = Date.prototype;

dproto.same = function(date) {
	return (+this) === (+date);
};

dproto.isLeapYear = function() {
	var year = this.getFullYear();
	return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
};

dproto.getDaysOfMonth = function(month) {
	month = month === undefined ? this.getMonth() : month;
	return [31, (this.isLeapYear() ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};

dproto.addYears = function(years) {
	var year = this.getFullYear() + years;
	this.setFullYear(year);

	return this;
};

dproto.addMonths = function(months) {
	var allMonths = this.getMonth() + months, 
		years= Math.floor(allMonths/12), 
		remainMonths = allMonths%12;

	years && this.addYears(years);
	this.setMonth(remainMonths);

	return this;
};
		
dproto.addDays = function(days) {
	var allDays = this.getDate() + days, remainDays = allDays, 
		daysOfMonth = this.getDaysOfMonth();

	while (remainDays >= daysOfMonth) {
		remainDays = remainDays - daysOfMonth;
		this.addMonths(1);

		daysOfMonth = this.getDaysOfMonth();
	}
	
	this.setDate(remainDays);

	return this;
};

UCDX.StatV2 = {
	stat: function(data, keys) {
		var results = [], result, val;

		keys.forEach(function(key, i) {
			if (!results[i]) {
				results[i] = { min: Number.MAX_VALUE, max: Number.MIN_VALUE };
			}
			result = results[i];

			data.forEach(function(v, j) {
				val = v[key];
				if (val < result.min) {
					result.min = val;
				}
				if (val > result.max) {
					result.max = val;
				}
			});
		});

		return results;
	},
	statAll: function(data, keys) {
		var results = this.stat(data, keys);
		var minMax = { min: Number.MAX_VALUE, max: Number.MIN_VALUE };
		results.forEach(function(r) {
			if (r.min < minMax.min) {
				minMax.min = r.min;
			}
			if (r.max > minMax.max) {
				minMax.max = r.max;
			}
		});
		return minMax;
	}
};

var __uuid = 0;
function _createID(prefix) {
    return 'ucd_' + prefix + '_' + (++__uuid);
}

/**
 * @namespace UCDX.Seed
 */
UCDX.Seed = UCDX.Seed || {
	UUID: _createID, 

	daysBetween: function(fromDate, endDate) {
		var ret = [], d = fromDate;
		while (!d.same(endDate)) {
			ret.push(d.toISOString().substr(0, 10));
			d = d.addDays(1);
		}

		return ret;
	}, 

	days: function(fromDate, n, step) {
		step = step || 1;
		var ret = [], d = fromDate, i = 0;
		while (i < n) {
			ret.push(d.toISOString().substr(0, 10));
			d = d.addDays(step);
			i++;
		}

		return ret;
	}
};

/**
 * @namespace UCDX.Data
 */
UCDX.Data = UCDX.Data || {
	/**
	 * 从SmartUE图表数据提取行列格式的数据
	 * 
	 * @param  {Array} data  SmartUE图表数据格式
	 * @return {Array}       行列格式的数据
	 */
	fromChart: function(data) {
		var ret = [], iret, len = data.length, m = len > 0 ? data[0].value.length : 0, i = 0, j;
		for (; i < m; i++) {
			iret = ret[i] || (ret[i] = []);
			for (j = 0; j < len; j++) {
				iret.push(data[j].value[i]);
			}
		}
		return ret;
	}, 
	
	/**
	 * 将行列格式的数据转化为SmartUE图表数据格式
	 * 
	 * @param  {Array}   a          行列格式的数据
	 * @param  {Boolean} forceArray 是否强制转换单个值为数组。每个value都应该是数组，对于有些例外。
	 * @return {Array}              SmartUE图表数据格式
	 */
	toChart: function (a, forceArray) {
		return this._toChart(this._verticalMergeArray(a), forceArray);
	},

	/**
	 * 将数组格式的数据转化为SmartUE图表数据格式
	 * 
	 * @param  {Array}   a          value数组
	 * @param  {Boolean} forceArray 是否强制转换单个值为数组。每个value都应该是数组，对于有些例外。
	 * @return {Array}              SmartUE图表数据格式
	 */
	_toChart: function (a, forceArray) {
		forceArray = forceArray === undefined ? true : false;
		if ($.isArray(a)) {
			return a.map(function(aa) {
				var value = (!forceArray || $.isArray(aa)) ? aa : [aa];
				return {
			        value: value
		    	};
			});
		} else {
			return [];
		}
	},


	/**
	 * 将行列格式的数组转换为value数组
	 * 
	 * @param  {Array} a 行列格式的数组
	 * @return {Array}   value数组
	 */
	_verticalMergeArray: function(a) {
		var ret = [], i = 0, n = a.length, aa, m = n > 0 ? a[0].length : 0, iret;
		for (; i < m; i++) {
			iret = ret[i] || (ret[i] = []);
			for (j = 0; j < n; j++) {
				aa = a[j][i];
				iret.push(aa);
			}
		}
		return ret;
	}
};


})(this, jQuery);

